15-112 Fundamentals of Programming

Notes - Lecture 1.5


Content

  1. Wrapping up
    1. break and continue
    2. Optional parameters
    3. Importing modules
    4. Approximate values for floats
    5. Short-circuit evaluation
    6. Conditional (if-else) expression
  2. Introduction to strings
    1. Some string operators
    2. String indexing and slicing
    3. Looping over strings
    4. String are immutable
    5. Some string related built-in functions
    6. Examples

break and continue

The break statement breaks out of a loop. In the example below, once counter reaches n (counter == n), the break statement is executed, which then makes the program go to line 8.

def countToN(n):
    counter = 1       
    while(True):
        print(counter)
        if(counter == n):
            break
        counter += 1
    print("bye!")

The continue statement breaks out of the current iteration and skips to the next iteration. In the example above, in iterations where x is even (x % 2 == 0), the continue statement is executed, which makes the program go to the next iteration, i.e. it skips line 6.

def sumOfOddsToN(n):
    total = 0
    for x in range(1, n+1):
        if(x % 2 == 0):
            continue
        total += x
    return total

Optional parameters

# Below y is an optional parameter.
# When calling the function, if a second argument is given, that value
# will be assigned to y. If a second argument is not given, by default,
# y will be assigned the value 10.  
def f(x, y=10): 
    return x+y

print(f(5))   # prints 15
print(f(5,6)) # prints 11

Importing modules

Call without importing
print(math.factorial(20))  # we did not first import the math module

# Python output:
#   NameError: name 'math' is not defined

Call with importing
print(math.factorial(20))  # we did not first import the math module

# Python output:
#   NameError: name 'math' is not defined

What does a module export?
# list all the functions in the math module
# (ignore items in __double_underscores__)
import math
print(dir(math))

# even better, read the online docs!
import webbrowser
input("Hit enter to see the online docs for the math module.")
webbrowser.open("https://docs.python.org/3/library/math.html")

Approximate values for floats

Approximate Values of Floating-Point Numbers
print(0.1 + 0.1 == 0.2)        # True, but...
print(0.1 + 0.1 + 0.1 == 0.3)  # False!
print(0.1 + 0.1 + 0.1)         # prints 0.30000000000000004 (uh oh)
print((0.1 + 0.1 + 0.1) - 0.3) # prints 5.55111512313e-17 (tiny, but non-zero!)

Equality Testing with almostEqual
print("The problem....")
d1 = 0.1 + 0.1 + 0.1
d2 = 0.3
print(d1 == d2)                # False (never use == with floats!)

print()
print("The solution...")
epsilon = 10**-10
print(abs(d2 - d1) < epsilon)  # True!

print()
print("Once again, using a useful helper function, almostEqual:")

def almostEqual(d1, d2):
    epsilon = 10**-10
    return (abs(d2 - d1) < epsilon)

d1 = 0.1 + 0.1 + 0.1
d2 = 0.3
print(d1 == d2)            # still False, of course
print(almostEqual(d1, d2)) # True, and now packaged in a handy reusable function!

Short-circuit evaluation

Short-Circuit Evaluation
def yes():
    return True

def no():
    return False

def crash():
    return 1/0 # crashes!

print(no() and crash()) # Works!
print(crash() and no()) # Crashes!
print (yes() and crash()) # Never runs (due to crash), but would also crash (without short-circuiting)

Once again, using the "or" operator
def yes():
    return True

def no():
    return False

def crash():
    return 1/0 # crashes!

print(yes() or crash()) # Works!
print(crash() or yes()) # Crashes!
print(no() or crash())  # Never runs (due to crash), but would also crash (without short-circuiting)

Yet another example
def isPositive(n):
    result = (n > 0)
    print("isPositive(",n,") =", result)
    return result

def isEven(n):
    result = (n % 2 == 0)
    print("isEven(",n,") =", result)
    return result

print("Test 1: isEven(-4) and isPositive(-4))")
print(isEven(-4) and isPositive(-4)) # Calls both functions
print("----------")
print("Test 2: isEven(-3) and isPositive(-3)")
print(isEven(-3) and isPositive(-3)) # Calls only one function!

Conditional (if-else) expression

if-else expression
# if-else expression (not an if-else statement!)

def abs7(n):
    return n if (n >= 0) else -n

print("abs7(5) =", abs7(5), "and abs7(-5) =", abs7(-5))




Introduction to Strings

A 'string' is simply a list of characters in order. A character is anything you can type on the keyboard in one keystroke, like a letter, a number, or a backslash. For example, "hello" is a string. Strings are a type of sequences becuase they allow us to store multiple characters, well, in a sequence.

Python strings are immutable which means they cannot be changed after they are created. Since strings can't be changed, we construct new strings as we go to represent computed values. So for example the expression ('hello' + 'there') takes in the 2 strings 'hello' and 'there' and builds a new string 'hellothere'.

1. Some string operators

String + and *
print("abc" + "def")
print("abc" * 3)
print("abc" + 3)  # error

The in operator
print("ring" in "strings")
print("wow" in "amazing!")
print("Yes" in "yes!")
print("" in "No way!")

2. String indexing and slicing

Indexing a single character
s = "abcdefgh"
print(s)
print(s[0])
print(s[1])
print(s[2])

print("-----------")
print(s[len(s)-1])
print(s[len(s)])  # crashes (string index out of range)

Negative indexes
s = "abcdefgh"
print(s)
print(s[-1])
print(s[-2])

Slicing a range of characters
s = "abcdefgh"
print(s)
print(s[0:3])
print(s[1:3])
print("-----------")
print(s[2:3])
print(s[3:3])

Slicing with default parameters
s = "abcdefgh"
print(s)
print(s[3:])
print(s[:3])
print(s[:])

Slicing with a step parameter
print("This is not as common, but perfectly ok.")
s = "abcdefgh"
print(s)
print(s[1:7:2])
print(s[1:7:3])

Reversing a string
s = "abcdefgh"

print("This works, but is confusing:")
print(s[::-1])

print("This also works, but is still confusing:")
print("".join(reversed(s)))

print("Best way: write your own reverseString() function:")

def reverseString(s):
    return s[::-1]

print(reverseString(s)) # crystal clear!

3. Looping over strings

"for" loop with indexes
s = "abcd"
for i in range(len(s)):
    print(i, s[i])

"for" loop without indexes
s = "abcd"
for c in s:
    print(c)

4. String are immutable

You cannot change strings! They are immutable.
s = "abcde"
s[2] = "z"  # Error! Cannot assign into s[i]

Instead, you must create a new string
s = "abcde"
s = s[:2] + "z" + s[3:]
print(s)

5. Some string related built-in functions

input(), str(), and len()
name = input("Enter your name: ")
print("Hi, " + name + ". Your name has " + str(len(name)) + " letters!")

chr() and ord()
print(ord("A")) # 65
print(chr(65))  # "A"
print(chr(ord("A")+1)) # ?

eval()
# eval() works but you should not use it!
s = "(3**2 + 4**2)**0.5"
print(eval(s))

# why not? Well...
s = "reformatMyHardDrive()"
print(eval(s)) # no such function!  But what if there was?

6. Examples

converting upper case to lower case
def convertToLowercase(character):
  distance = ord("a") - ord("A")
  return chr(ord(character) + distance)

isPalindrome
# There are many ways to write isPalindrome(s)
# Here are several.  Which way is best?

def reverseString(s):
    return s[::-1]

def isPalindrome1(s):
    return (s == reverseString(s))

def isPalindrome2(s):
    for i in range(len(s)):
        if (s[i] != s[len(s)-1-i]):
            return False
    return True

def isPalindrome3(s):
    for i in range(len(s)):
        if (s[i] != s[-1-i]):
            return False
    return True

def isPalindrome4(s):
    while (len(s) > 1):
        if (s[0] != s[-1]):
            return False
        s = s[1:-1]
    return True

print(isPalindrome1("abcba"), isPalindrome1("abca"))
print(isPalindrome2("abcba"), isPalindrome2("abca"))
print(isPalindrome3("abcba"), isPalindrome3("abca"))
print(isPalindrome4("abcba"), isPalindrome4("abca"))



Valid CSS! Valid XHTML 1.0 Strict